题目描述:
給定一個排序陣列和一個目標值,請在陣列中找到目標值,並返回其索引。如果目標值不在陣列中,則返回它將會按順序插入的位置。
你必須編寫一個時間複雜度為 O(log n)
的算法。
Example 1:
nums = [1,3,5,6]
, target = 5
2
Example 2:
nums = [1,3,5,6]
, target = 2
1
解題思路
在 LeetCode 題目中,經常會遇到需要在排序陣列中尋找目標值的問題。這類型題目通常會使用 Binary Search(二分搜索法) 來尋找目標值。
二分搜索法的基本思路是:在已排序的陣列中,先找到中間值,然後將陣列分為兩部分。如果目標值小於中間值,則在左半部分繼續進行二分搜索;如果目標值大於中間值,則在右半部分繼續進行搜索。由於每次搜索都將陣列的數量減少一半,因此時間複雜度為 O(log n)
,這正好符合本題的要求。
值得一提的是,在執行二分搜索法時,使用頭尾雙指針 left
和 right
來表示搜索範圍。結束條件有兩種可能:
left <= right
:適用於標準的二分查找,當需要遍歷整個搜索區間並確保所有元素都被檢查到時使用。left < right
:適用於找到某個條件下的插入位置或其他邊界問題時使用。讀者千萬不要一概而論地使用 left <= right
,因為這樣很容易導致錯誤的結果。那麼,如何判斷應該使用哪種結束條件呢?答案很簡單——像這道題一樣,畫出二分搜索法的過程,特別是最後關鍵的一步,來確定應該採用哪個結束條件。通過仔細分析和演算,可以避免因錯誤選擇結束條件而導致的計算偏差。
var searchInsert = function(nums, target) {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (nums[mid] === target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
};
時間複雜度:
O(log n)
,因為我們使用了二分搜索算法。
空間複雜度:O(1)
,只使用了常數空間來存儲指針。
總結:
這道題目可以歸類為「Binary Search」。很明顯,這題的設計目的是讓讀者學習如何使用二分搜索法來尋找目標值。之後的 LeetCode 題目中,二分搜索法仍會經常出現,只是題目可能會有所變形而不易察覺。不過,當題目中出現「排序陣列」和「搜尋唯一解」這兩個關鍵詞時,使用二分搜索法的可能性就會很高,不妨先嘗試這個方法來解題,往往問題一下就解決了。